export declare type Angle = 'deg' | 'rad' | 'grad' | 'turn'

// 获取角度
export const getDeg = (angle: string): number => {
  if (!angle) return 0

  if (angle.endsWith('deg')) return parseFloat(angle)

  if (angle.endsWith('rad')) return parseFloat(angle) * 180 / Math.PI

  if (angle.endsWith('grad')) return parseFloat(angle) * 0.9

  if (angle.endsWith('turn')) return parseFloat(angle) * 360

  throw new Error(`[Error] argument[0] must be end with 'deg', 'rad', 'grad', 'turn' but got ${angle}`)
}

// 获取弧度
export const getRad = (angle: string): number => {
  if (!angle) return 0

  if (angle.endsWith('deg')) return parseFloat(angle) * Math.PI / 180

  if (angle.endsWith('rad')) return parseFloat(angle)

  if (angle.endsWith('grad')) return parseFloat(angle) * Math.PI / 200

  if (angle.endsWith('turn')) return parseFloat(angle) * 2 * Math.PI

  throw new Error(`[Error] argument[0] must be end with 'deg', 'rad', 'grad', 'turn' but got ${angle}`)
}

// 获取梯度
export const getGrad = (angle: string): number => {
  if (!angle) return 0

  if (angle.endsWith('deg')) return parseFloat(angle) * 10 / 9

  if (angle.endsWith('rad')) return parseFloat(angle) * 200 / Math.PI

  if (angle.endsWith('grad')) return parseFloat(angle)

  if (angle.endsWith('turn')) return parseFloat(angle) * 400

  throw new Error(`[Error] argument[0] must be end with 'deg', 'rad', 'grad', 'turn' but got ${angle}`)
}

// 获取圈数
export const getTurn = (angle: string): number => {
  if (!angle) return 0

  if (angle.endsWith('deg')) return parseFloat(angle) / 360

  if (angle.endsWith('rad')) return parseFloat(angle) / (2 * Math.PI)

  if (angle.endsWith('grad')) return parseFloat(angle) / 400

  if (angle.endsWith('turn')) return parseFloat(angle)

  throw new Error(`[Error] argument[0] must be end with 'deg', 'rad', 'grad', 'turn' but got ${angle}`)
}

// 角度转换 (1 turn = 360 deg = 2π rad = 400 grad)
export const getAngle = (angle: string, unit: Angle): number => {
  if (!angle) return 0

  if (!unit) throw new Error(`[Error] arguments[1] is required but got ${unit}`)

  if (!['deg', 'rad', 'grad', 'turn'].includes(unit)) throw new Error(`[Error] arguments[1] must be one of 'deg', 'rad', 'grad', 'turn' but got ${unit}`)

  switch (unit) {
    case 'deg':
      return getDeg(angle)

    case 'rad':
      return getRad(angle)

    case 'grad':
      return getGrad(angle)

    case 'turn':
      return getTurn(angle)
  }
}

// 获取两点之间的距离 (勾股定理)
export declare type GetDistance = {
  (x1: number, y1: number, x2: number, y2: number): number
  ([x1, y1]: [number, number], [x2, y2]: [number, number]): number
}

export const getDistance: GetDistance = (x1: any, y1: any, x2?: number, y2?: number) => {
  if (!x1) throw new Error(`[Error] arguments[0] is required but got ${x1}`)
  if (!y1) throw new Error(`[Error] arguments[1] is required but got ${x1}`)

  if (Array.isArray(x1) && !Array.isArray(y1)) throw new Error(`[Error] typeof arguments[1] must be same of typeof arguments[0]`)
  if (!Array.isArray(x1) && Array.isArray(y1)) throw new Error(`[Error] typeof arguments[1] must be same of typeof arguments[0]`)

  if (Array.isArray(x1) && Array.isArray(y1)) [x1, y1, x2, y2] = x1.concat(y1)

  return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
}